package com.slimbloody;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;
import io.grpc.netty.shaded.io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.nameresolver.DiscoveryClientResolverFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tensorflow.serving.Predict;

import javax.net.ssl.SSLException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;

@RequestMapping(value = "/call")
@RestController
@Slf4j
public class CallController {
  @Autowired
  private CallService callService;

  @Autowired
  private DiscoveryClientResolverFactory discoveryClientResolverFactory;

  @PostMapping("pb")
  public void pb() {
    // 文件名（相对于 resources 文件夹）
    String fileName = "request.bin";

    // 获取类加载器
    ClassLoader classLoader = CallController.class.getClassLoader();

    try (InputStream inputStream = classLoader.getResourceAsStream(fileName)) {
      if (inputStream == null) {
        throw new IOException("File not found: " + fileName);
      }

      // 从 InputStream 中读取并反序列化
      Predict.PredictRequest request = Predict.PredictRequest.parseFrom(inputStream);

      // 打印反序列化后的对象
      JsonFormat.Printer printer = JsonFormat.printer();
      String json = printer.print(request);
      System.out.println(json);

      ByteString tensorContent = request.getInputsMap()
        .get("sale_rank_31d").getTensorContent();
      ByteBuffer buffer = tensorContent.asReadOnlyByteBuffer().order(ByteOrder.LITTLE_ENDIAN);
      int numFloats = buffer.remaining() / Float.BYTES;

      List<Float> floatList = new ArrayList<>(numFloats);
      for (int i = 0; i < numFloats; i++) {
        floatList.add(buffer.getFloat());
      }

      System.out.println(floatList);
      System.out.println();
    } catch (InvalidProtocolBufferException e) {
      System.err.println("Invalid Protocol Buffer data: " + e.getMessage());
    } catch (IOException e) {
      System.err.println("Error reading file: " + e.getMessage());
    }
  }

  @PostMapping("/callhalf")
  public String callHalf() {
    return callService.callHalf();
  }

  @PostMapping("/callBatch")
  public String callBatch() {
    int[] batchSize = {300, 600, 900};
    StopWatch stopWatch = new StopWatch();
    for (int size: batchSize) {
      stopWatch.start("size: " + size);
      String res = callService.callzh(size);
      stopWatch.stop();
      log.info("{}, cost: {}", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis());
      log.info(res);
    }
    return "";
  }

  @PostMapping("/callzh")
  public String callzh(@RequestBody Integer size) {
    return callService.callzh(size);
  }


  @PostMapping("/ssl")
  public void call2() {
    try {
      SslContext sslContext = SslContextBuilder
        .forClient()
        .trustManager(InsecureTrustManagerFactory.INSTANCE) // 不验证证书
        .build();
    } catch (SSLException e) {
      throw new RuntimeException(e);
    }
  }

  // @PostMapping("/abtest")
  // public void abtest() {
  //   // 获取Class对象
  //   Class<?> clazz = discoveryClientResolverFactory.getClass();
  //
  //   // 获取私有属性
  //   Field privateField = null;
  //   try {
  //     privateField = clazz.getDeclaredField("discoveryClientNameResolvers");
  //     // 设置私有属性的访问权限
  //     privateField.setAccessible(true);
  //     // 获取私有属性的值
  //     Set<DiscoveryClientNameResolver> discoveryClientNameResolvers = (Set<DiscoveryClientNameResolver>) privateField.get(discoveryClientResolverFactory);
  //     log.info("discoveryClientNameResolvers: {}", discoveryClientNameResolvers);
  //   } catch (NoSuchFieldException e) {
  //     throw new RuntimeException(e);
  //   } catch (IllegalAccessException e) {
  //     throw new RuntimeException(e);
  //   }
  // }
}
